#include "Meld.h"
#include "Card.h"
#include "Set.cpp"
#include "SetIter.cpp"
#include <iostream>
#include <string>

using std::ostream;
using std::istream;
using std::cout;
using std::cin;
using std::endl;
using std::string;

Meld:: Meld(){
  cardSet = Set<Card>();
}

Meld:: Meld(Set<Card> thisSet){
  cardSet = thisSet;
}

Meld:: Meld(const Meld& fromMeld){
  cardSet = fromMeld.getCardSet();
}

Meld:: ~Meld(){
}

//Checkers

bool Meld::isValid() const{
  return false;
}

//This method checks the Meld for validity and returns 1 if it is a Run, -1 if it is a Group, and 0 if it is an invalid Meld.
int Meld::validify() const{
  if(cardSet.size()<3)
    return 0;

  SetIter<Card> cardIter(cardSet);
  Card prevCard, thisCard, blankCard;
  int numAces = 0;
  bool isGroup=true;
  bool isRun=true;
  while(cardIter.hasNext()){
    prevCard = thisCard;
    thisCard = cardIter.next();
    if(thisCard.face==1)
      numAces++;
    if(thisCard.face==2||thisCard.face==13)
      numAces--;
    //cout<<"NumAces: "<<numAces<<endl;
    //cout<<"Current card: "<<thisCard<<endl;
    if(!(prevCard==blankCard)){
      if(isRun){
	isRun = isRun && thisCard.suit==prevCard.suit && ((!(thisCard==prevCard) && thisCard.face==prevCard.face+1)||(thisCard.face==1||prevCard.face==1));
	//cout<<"Previous card: "<<prevCard<<endl;
      }
      if(isGroup)
	isGroup = isGroup && (thisCard.face==prevCard.face) && !(thisCard==prevCard);
      //cout<<"isGroup: "<<isGroup<<endl;
      //cout<<"isRun: "<<isRun<<endl;
      
    }
    
  }
  isRun = isRun&&numAces<=0;
  //cout<<"isGroup: "<<isGroup<<endl;
  //cout<<"isRun: "<<isRun<<endl;
  if(isGroup)
    return -1;
  else if(isRun)
    return 1;
  else
    return 0;
}

int Meld::size() const{
  return cardSet.size();
}

bool Meld::isEmpty() const{
  return cardSet.size()==0;
}

Meld* Meld::split(int toIndex){
  SetIter<Card> cardIter(cardSet);
  Set<Card> reMeld;
  while(cardSet.size()>toIndex){
    cout<<cardSet.size()<<endl;
    reMeld.add(cardSet.remove(toIndex));
    cout<<reMeld<<endl;
  }
  return new Meld(reMeld);
}

void Meld::add(const Meld& adMeld){
  Set<Card> thisSet = adMeld.getCardSet();
  SetIter<Card> cardAdd(thisSet);

  Card thisCard;
  while(cardAdd.hasNext()){
    thisCard = cardAdd.next();
    //    cout<<"CARD SIZE: "<<thisCard.size()<<endl;
    //cout<<"thisCard to add: "<<thisCard<<endl;
    //cout<<"Stuff: "<<thisCard.face<<" "<<thisCard.suit<<endl;
    cardSet.add(thisCard);
    //cout<<"CARDSET: "<<cardSet<<endl;
  }
}

void Meld::add(const Card& adCard){
  cardSet.add(adCard);
}

//Getters
Set<Card> Meld::getCardSet() const{
  return cardSet;
}

Set<Card> Meld::getValidCards(){
  //  cout<<"in base type\n";
  return Set<Card>();
}

ostream& Meld::write(ostream & ost) const{
  SetIter<Card> cardIter(cardSet);
  while(cardIter.hasNext())
    ost<<cardIter.next()<<" ";
  return ost;
}

ostream& Meld::printIndexes(ostream& ost) const{
  SetIter<Card> cardIter(cardSet);
  int i = 1;
  while(cardIter.hasNext()){
    ost<<"|"<<i<<" "<<cardIter.next()<<"| ";
    i++;
  }
  return ost;
}

ostream & operator<<(ostream &os, const Meld &is){
  if(!is.isEmpty())
    is.write(os);
  return os;
}
